﻿/*************************************************************************
 * Created by OhZee Creative, LLC
 * 2013
 * This code is licensed under Microsoft Public License (Ms-PL)
 * http://opensource.org/licenses/ms-pl
 * http://ozframework.codeplex.com/
 *************************************************************************/

namespace OhZeeCreative.Helpers
{
	using System;
	using System.Collections.Generic;

#if SILVERLIGHT
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Data;
#endif

#if NETFX_CORE
	using Windows.UI.Xaml;
	using Windows.UI.Xaml.Data;
	using Windows.UI.Xaml.Media;
#endif

    public static class DependencyHelper
	{
		public static bool CoerceMinimum(DependencyObject owner, DependencyPropertyChangedEventArgs change, DependencyProperty property, int minimum)
		{
			if ((int)change.NewValue < minimum)
			{
				owner.SetValue(property, Math.Max(minimum, (int)change.OldValue));
				return true;
			}
			
			return false;
		}

		public static bool CoerceMinimum(DependencyObject owner, DependencyPropertyChangedEventArgs change, DependencyProperty property, double minimum, bool inclusive = true)
		{
			if (inclusive && (double)change.NewValue < minimum)
			{
				owner.SetValue(property, Math.Max(minimum, (double)change.OldValue));
				return true;
			}
			else if (!inclusive && (double)change.NewValue <= minimum)
			{
				owner.SetValue(property, (double)change.OldValue);
				return true;
			}

			return false;
		}

		public static bool CoerceRange(DependencyObject owner, DependencyPropertyChangedEventArgs change, DependencyProperty property, int minimum, int maximum)
		{
			if ((int)change.NewValue < minimum)
			{
				owner.SetValue(property, Math.Max(minimum, (int)change.OldValue));
				return true;
			}

			if ((int)change.NewValue > maximum)
			{
				owner.SetValue(property, Math.Min(maximum, (int)change.OldValue));
				return true;
			}

			return false;
		}

		public static bool CoerceRange(DependencyObject owner,  DependencyPropertyChangedEventArgs change, DependencyProperty property, double minimum, double maximum)
		{
			if ((double)change.NewValue < minimum)
			{
				owner.SetValue(property, Math.Max(minimum, (double)change.OldValue));
				return true;
			}

			if ((double)change.NewValue > maximum)
			{
				owner.SetValue(property, Math.Min(maximum, (double)change.OldValue));
				return true;
			}

			return false;
		}

		public static void ClearBinding(DependencyObject target, DependencyProperty targetProperty)
		{
			target.ClearValue(targetProperty);
		}

		public static void Bind(DependencyObject target, DependencyProperty targetProperty, object source, string sourcePropertyName, BindingMode bindingMode)
		{
			Binding binding = new Binding()
			{
				Mode = bindingMode,
				Source = source,
				Path = new PropertyPath(sourcePropertyName)
			};
			BindingOperations.SetBinding(target, targetProperty, binding);
		}

		public static IEnumerable<DependencyObject> GetVisualDescendants(this DependencyObject parent, Type childType)
		{
			int children = VisualTreeHelper.GetChildrenCount(parent);

			for (int i = 0; i < children; i++)
			{
				DependencyObject child = VisualTreeHelper.GetChild(parent, i);

				if (child.GetType().Equals(childType))
				{
					yield return child;
				}

				foreach (DependencyObject dob in child.GetVisualDescendants(childType))
				{
					yield return dob;
				}
			}
		}
	}
}
